
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.InteropServices;
using System.Xml;
using System.Text;

using Weazel.Toad.TextEditor.Document;
using Weazel.Toad.TextEditor.Actions;
 
namespace Weazel.Toad.TextEditor
{
	/// <summary>
	/// This class is used for a basic text area control
	/// </summary>
	[ToolboxItem(false)]
	public class TextEditorControl : TextEditorControlBase
	{
		protected Panel textAreaPanel     = new Panel();

		TextAreaControl textAreaControl;
    public override TextAreaControl TextAreaControl
    {
      get
      {
        return textAreaControl;
      }
    }

    public TextEditorControl()
		{
			SetStyle(ControlStyles.ContainerControl, true);
			SetStyle(ControlStyles.Selectable, true);
			
			textAreaPanel.Dock = DockStyle.Fill;
			
			Document = (new DocumentFactory()).CreateDocument();
			Document.Highlighter = HighlighterFactory.CreateHighlightingStrategy();
			
			textAreaControl  = new TextAreaControl(this);
			textAreaControl.Dock = DockStyle.Fill;
			textAreaPanel.Controls.Add(textAreaControl);
			InitializeTextAreaControl(textAreaControl);
			Controls.Add(textAreaPanel);
			ResizeRedraw = true;
			Document.UpdateCommited += new EventHandler(CommitUpdateRequested);
			OptionsChanged();
		}
		
		protected virtual void InitializeTextAreaControl(TextAreaControl newControl)
		{
		}
		
		public override void OptionsChanged()
		{
			textAreaControl.OptionsChanged();
		}

    public bool EnableUndo {
			get {
				return Document.UndoStack.CanUndo;
			}
		}
		public bool EnableRedo {
			get {
				return Document.UndoStack.CanRedo;
			}
		}

		public void Undo()
		{
			if (Document.ReadOnly) {
				return;
			}
			if (Document.UndoStack.CanUndo) {
				BeginUpdate();
				Document.UndoStack.Undo();
				
				Document.UpdateQueue.Clear();
				Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
				this.textAreaControl.TextArea.UpdateMatchingBracket();
				EndUpdate();
			}
		}
		
		public void Redo()
		{
			if (Document.ReadOnly) {
				return;
			}
			if (Document.UndoStack.CanRedo) {
				BeginUpdate();
				Document.UndoStack.Redo();
				
				Document.UpdateQueue.Clear();
				Document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.WholeTextArea));
				this.textAreaControl.TextArea.UpdateMatchingBracket();
				EndUpdate();
			}
		}
		
		public void SetHighlighting(string name)
		{
			Document.Highlighter = HighlighterFactory.CreateHighlightingStrategy(name);
		}
				
#region Update Methods
		public override void EndUpdate()
		{
			base.EndUpdate();
			Document.CommitUpdate();
		}
		
		void CommitUpdateRequested(object sender, EventArgs e)
		{
			if (IsUpdating) {
				return;
			}
			foreach (TextAreaUpdate update in Document.UpdateQueue) {
				switch (update.TextAreaUpdateType) {
					case TextAreaUpdateType.PositionToEnd:
						this.textAreaControl.TextArea.UpdateToEnd(update.Position.Y);
						break;
					case TextAreaUpdateType.PositionToLineEnd:
					case TextAreaUpdateType.SingleLine:
						this.textAreaControl.TextArea.UpdateLine(update.Position.Y);
						break;
					case TextAreaUpdateType.SinglePosition:
						this.textAreaControl.TextArea.UpdateLine(update.Position.Y, update.Position.X, update.Position.X);
						break;
					case TextAreaUpdateType.LinesBetween:
						this.textAreaControl.TextArea.UpdateLines(update.Position.X, update.Position.Y);
						break;
					case TextAreaUpdateType.WholeTextArea:
						this.textAreaControl.TextArea.Invalidate();
						break;
				}
			}
			Document.UpdateQueue.Clear();
			this.textAreaControl.TextArea.Update();
		}
#endregion
	
	}
}
